﻿using System;
using System.Text;

namespace UtilZ.Dotnet.Ex.Base
{
    /// <summary>
    /// Array辅助类
    /// </summary>
    public static partial class ArrayEx
    {

        private static int? _maxLength = null;
        /// <summary>
        /// 获取或设置僵尸数组最大长度
        /// </summary>
        public static int MaxLength
        {
            get
            {
                if (_maxLength.HasValue)
                {
                    return _maxLength.Value;
                }
                else
                {
#if CORE
                    return Array.MaxLength;
#else
                    return int.MaxValue;
#endif
                }
            }
            set
            {
                if (value <= 0)
                {
                    throw new ArgumentOutOfRangeException("数组最大长度必须大于0");
                }

                _maxLength = value;
            }
        }


        /// <summary>
        /// 数组ToString
        /// </summary>
        /// <typeparam name="T">数据元素类型</typeparam>
        /// <param name="arr">数组</param>
        /// <param name="separator">元素分隔符</param>
        /// <returns>String</returns>
        public static string ToString<T>(this T[] arr, char separator)
        {
            if (arr == null)
            {
                return string.Empty;
            }

            StringBuilder sb = new StringBuilder();
            for (long i = 0; i < arr.LongLength; i++)
            {
                if (sb.Length > 0)
                {
                    sb.Append(separator);
                }

                sb.Append(arr[i]);
            }

            return sb.ToString();
        }

        /// <summary>
        /// 数组ToString
        /// </summary>
        /// <typeparam name="T">数据元素类型</typeparam>
        /// <param name="arr">数组</param>
        /// <param name="separator">元素分隔符</param>
        /// <param name="startIndex">起始位置</param>
        /// <param name="count">元素个数</param>
        /// <returns></returns>
        public static string ToString<T>(this T[] arr, char separator, int startIndex, int count)
        {
            if (arr == null)
            {
                return string.Empty;
            }

            if (arr == null)
            {
                return string.Empty;
            }

            if (startIndex < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(startIndex));
            }

            if (count < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            int end = startIndex + count;
            if (end > arr.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            StringBuilder sb = new StringBuilder();
            for (long i = startIndex; i < end; i++)
            {
                if (sb.Length > 0)
                {
                    sb.Append(separator);
                }

                sb.Append(arr[i]);
            }

            return sb.ToString();
        }


        /// <summary>
        /// 数组ToString
        /// </summary>
        /// <typeparam name="T">数据元素类型</typeparam>
        /// <param name="arr">数组</param>
        /// <param name="separator">元素分隔符</param>
        /// <returns>String</returns>
        public static string ToString<T>(this T[] arr, string separator)
        {
            if (arr == null)
            {
                return string.Empty;
            }

            StringBuilder sb = new StringBuilder();
            for (long i = 0; i < arr.LongLength; i++)
            {
                if (sb.Length > 0)
                {
                    sb.Append(separator);
                }

                sb.Append(arr[i]);
            }

            return sb.ToString();
        }

        /// <summary>
        /// 数组ToString
        /// </summary>
        /// <typeparam name="T">数据元素类型</typeparam>
        /// <param name="arr">数组</param>
        /// <param name="separator">元素分隔符</param>
        /// <param name="startIndex">起始位置</param>
        /// <param name="count">元素个数</param>
        /// <returns></returns>
        public static string ToString<T>(this T[] arr, string separator, int startIndex, int count)
        {
            if (arr == null)
            {
                return string.Empty;
            }

            if (startIndex < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(startIndex));
            }

            if (count < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            int end = startIndex + count;
            if (end > arr.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            StringBuilder sb = new StringBuilder();
            for (var i = startIndex; i < end; i++)
            {
                if (sb.Length > 0)
                {
                    sb.Append(separator);
                }

                sb.Append(arr[i]);
            }

            return sb.ToString();
        }




        /// <summary>
        /// 数组ToString
        /// </summary>
        /// <typeparam name="T">数据元素类型</typeparam>
        /// <param name="arr">二维数组</param>
        /// <param name="separator">元素分隔符</param>
        /// <returns>String</returns>
        public static string ToString<T>(this T[][] arr, char separator)
        {
            if (arr == null)
            {
                return string.Empty;
            }

            StringBuilder sb = new StringBuilder();
            for (long i = 0; i < arr.LongLength; i++)
            {
                if (sb.Length > 0)
                {
                    sb.AppendLine();
                }

                if (arr[i] == null)
                {
                    continue;
                }

                for (long j = 0; j < arr[i].LongLength; j++)
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(separator);
                    }

                    sb.Append(arr[i][j]);
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// 数组ToString
        /// </summary>
        /// <typeparam name="T">数据元素类型</typeparam>
        /// <param name="arr">二维数组</param>
        /// <param name="separator">元素分隔符</param>
        /// <param name="startRowIndex">起始行索引</param>
        /// <param name="rowCount">行数</param>
        /// <param name="startColumnIndex">起始列索引</param>
        /// <param name="columnCount">列数</param>
        /// <returns>String</returns>
        public static string ToString<T>(this T[][] arr, char separator, int startRowIndex, int rowCount, int startColumnIndex, int columnCount)
        {
            if (arr == null)
            {
                return string.Empty;
            }

            if (startRowIndex < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(startRowIndex));
            }

            if (rowCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(rowCount));
            }

            if (startColumnIndex < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(startColumnIndex));
            }

            if (columnCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(columnCount));
            }

            var endRow = startRowIndex + rowCount;
            var endColumn = startColumnIndex + columnCount;

            if (endRow > arr.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(rowCount));
            }

            StringBuilder sb = new StringBuilder();

            for (var i = startRowIndex; i < endRow; i++)
            {
                if (sb.Length > 0)
                {
                    sb.AppendLine();
                }

                if (arr[i] == null)
                {
                    continue;
                }

                if (endColumn > arr[i].Length)
                {
                    throw new ArgumentOutOfRangeException(nameof(columnCount));
                }

                for (var j = startColumnIndex; j < endColumn; j++)
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(separator);
                    }

                    sb.Append(arr[i][j]);
                }
            }

            return sb.ToString();
        }




        /// <summary>
        /// 数组ToString
        /// </summary>
        /// <typeparam name="T">数据元素类型</typeparam>
        /// <param name="arr">二维数组</param>
        /// <param name="separator">元素分隔符</param>
        /// <returns>String</returns>
        public static string ToString<T>(this T[][] arr, string separator)
        {
            if (arr == null)
            {
                return string.Empty;
            }

            StringBuilder sb = new StringBuilder();
            for (long i = 0; i < arr.LongLength; i++)
            {
                if (sb.Length > 0)
                {
                    sb.AppendLine();
                }

                if (arr[i] == null)
                {
                    continue;
                }

                for (long j = 0; j < arr[i].LongLength; j++)
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(separator);
                    }

                    sb.Append(arr[i][j]);
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// 数组ToString
        /// </summary>
        /// <typeparam name="T">数据元素类型</typeparam>
        /// <param name="arr">二维数组</param>
        /// <param name="separator">元素分隔符</param>
        /// <param name="startRowIndex">起始行索引</param>
        /// <param name="rowCount">行数</param>
        /// <param name="startColumnIndex">起始列索引</param>
        /// <param name="columnCount">列数</param>
        /// <returns>String</returns>
        public static string ToString<T>(this T[][] arr, string separator, int startRowIndex, int rowCount, int startColumnIndex, int columnCount)
        {
            if (arr == null)
            {
                return string.Empty;
            }

            if (startRowIndex < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(startRowIndex));
            }

            if (rowCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(rowCount));
            }

            if (startColumnIndex < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(startColumnIndex));
            }

            if (columnCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(columnCount));
            }

            var endRow = startRowIndex + rowCount;
            var endColumn = startColumnIndex + columnCount;

            if (endRow > arr.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(rowCount));
            }

            StringBuilder sb = new StringBuilder();
            for (var i = startRowIndex; i < endRow; i++)
            {
                if (sb.Length > 0)
                {
                    sb.AppendLine();
                }

                if (arr[i] == null)
                {
                    continue;
                }

                if (endColumn > arr[i].Length)
                {
                    throw new ArgumentOutOfRangeException(nameof(columnCount));
                }

                for (var j = startColumnIndex; j < endColumn; j++)
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(separator);
                    }

                    sb.Append(arr[i][j]);
                }
            }

            return sb.ToString();
        }




        /// <summary>
        /// 数组ToString
        /// </summary>
        /// <typeparam name="T">数据元素类型</typeparam>
        /// <param name="arr">二维数组</param>
        /// <param name="separator">元素分隔符</param>
        /// <returns>String</returns>
        public static string ToString<T>(this T[,] arr, char separator)
        {
            if (arr == null)
            {
                return string.Empty;
            }

            StringBuilder sb = new StringBuilder();
            var length1 = arr.GetLongLength(0);
            var length2 = arr.GetLongLength(1);

            for (var i = 0; i < length1; i++)
            {
                if (sb.Length > 0)
                {
                    sb.AppendLine();
                }

                for (var j = 0; j < length2; j++)
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(separator);
                    }

                    sb.Append(arr[i, j]);
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// 数组ToString
        /// </summary>
        /// <typeparam name="T">数据元素类型</typeparam>
        /// <param name="arr">二维数组</param>
        /// <param name="separator">元素分隔符</param>
        /// <param name="startRowIndex">起始行索引</param>
        /// <param name="rowCount">行数</param>
        /// <param name="startColumnIndex">起始列索引</param>
        /// <param name="columnCount">列数</param>
        /// <returns>String</returns>
        public static string ToString<T>(this T[,] arr, char separator, int startRowIndex, int rowCount, int startColumnIndex, int columnCount)
        {
            if (arr == null)
            {
                return string.Empty;
            }

            if (startRowIndex < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(startRowIndex));
            }

            if (rowCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(rowCount));
            }

            if (startColumnIndex < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(startColumnIndex));
            }

            if (columnCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(columnCount));
            }

            var length1 = arr.GetLongLength(0);
            var length2 = arr.GetLongLength(1);
            var endRow = startRowIndex + rowCount;
            var endColumn = startColumnIndex + columnCount;

            if (endRow > length1)
            {
                throw new ArgumentOutOfRangeException(nameof(rowCount));
            }

            if (endColumn > length2)
            {
                throw new ArgumentOutOfRangeException(nameof(columnCount));
            }

            StringBuilder sb = new StringBuilder();

            for (var i = startRowIndex; i < endRow; i++)
            {
                if (sb.Length > 0)
                {
                    sb.AppendLine();
                }

                for (var j = startColumnIndex; j < endColumn; j++)
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(separator);
                    }

                    sb.Append(arr[i, j]);
                }
            }

            return sb.ToString();
        }





        /// <summary>
        /// 数组ToString
        /// </summary>
        /// <typeparam name="T">数据元素类型</typeparam>
        /// <param name="arr">二维数组</param>
        /// <param name="separator">元素分隔符</param>
        /// <returns>String</returns>
        public static string ToString<T>(this T[,] arr, string separator)
        {
            if (arr == null)
            {
                return string.Empty;
            }

            StringBuilder sb = new StringBuilder();
            var length1 = arr.GetLongLength(0);
            var length2 = arr.GetLongLength(1);
            for (var i = 0; i < length1; i++)
            {
                if (sb.Length > 0)
                {
                    sb.AppendLine();
                }

                for (var j = 0; j < length2; j++)
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(separator);
                    }

                    sb.Append(arr[i, j]);
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// 数组ToString
        /// </summary>
        /// <typeparam name="T">数据元素类型</typeparam>
        /// <param name="arr">二维数组</param>
        /// <param name="separator">元素分隔符</param>
        /// <param name="startRowIndex">起始行索引</param>
        /// <param name="rowCount">行数</param>
        /// <param name="startColumnIndex">起始列索引</param>
        /// <param name="columnCount">列数</param>
        /// <returns>String</returns>
        public static string ToString<T>(this T[,] arr, string separator, int startRowIndex, int rowCount, int startColumnIndex, int columnCount)
        {
            if (arr == null)
            {
                return string.Empty;
            }

            if (startRowIndex < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(startRowIndex));
            }

            if (rowCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(rowCount));
            }

            if (startColumnIndex < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(startColumnIndex));
            }

            if (columnCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(columnCount));
            }

            var length1 = arr.GetLongLength(0);
            var length2 = arr.GetLongLength(1);
            var endRow = startRowIndex + rowCount;
            var endColumn = startColumnIndex + columnCount;

            if (endRow > length1)
            {
                throw new ArgumentOutOfRangeException(nameof(rowCount));
            }

            if (endColumn > length2)
            {
                throw new ArgumentOutOfRangeException(nameof(columnCount));
            }

            StringBuilder sb = new StringBuilder();

            for (var i = startRowIndex; i < endRow; i++)
            {
                if (sb.Length > 0)
                {
                    sb.AppendLine();
                }

                for (var j = startColumnIndex; j < endColumn; j++)
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(separator);
                    }

                    sb.Append(arr[i, j]);
                }
            }

            return sb.ToString();
        }

    }

}
